package com.george.gateway.config;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import lombok.RequiredArgsConstructor;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.cloud.gateway.config.GatewayProperties;
import org.springframework.cloud.gateway.route.RouteLocator;
import org.springframework.cloud.gateway.support.NameUtils;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.http.ResponseEntity;
import org.springframework.http.client.SimpleClientHttpRequestFactory;
import org.springframework.web.client.RestTemplate;
import springfox.documentation.swagger.web.SwaggerResource;
import springfox.documentation.swagger.web.SwaggerResourcesProvider;

import java.util.ArrayList;
import java.util.List;

/**
 * @title: SwaggerResourceConfig.java
 * @description: swagger多服务模块文档聚合配置类
 * @author: George
 * @date: 2023/6/30 11:15
 */
@Configuration
@Primary
@RequiredArgsConstructor
public class SwaggerResourceConfig implements SwaggerResourcesProvider {

    private final RouteLocator routeLocator;

    private final GatewayProperties gatewayProperties;

    private final DiscoveryClient discoveryClient;


    @Override
    public List<SwaggerResource> get() {
        List<SwaggerResource> resources = new ArrayList<>();
        List<String> routes = new ArrayList<>();
        //读取网关服务路由配置，组装swagger文档分组列表
        routeLocator.getRoutes().subscribe(route -> routes.add(route.getId()));
        gatewayProperties.getRoutes().stream().filter(routeDefinition -> routes.contains(routeDefinition.getId()) && checkServiceHealth(routeDefinition.getId())).forEach(route -> {
            route.getPredicates().stream()
                    .filter(predicateDefinition -> ("Path").equalsIgnoreCase(predicateDefinition.getName()))
                    .forEach(predicateDefinition -> resources.add(swaggerResource(route.getId(),
                            predicateDefinition.getArgs().get(NameUtils.GENERATED_NAME_PREFIX + "0")
                                    .replace("/**", "/v3/api-docs"))));
        });

        return resources;
    }

    private SwaggerResource swaggerResource(String name, String location) {
        SwaggerResource swaggerResource = new SwaggerResource();
        swaggerResource.setName(name);
        swaggerResource.setLocation(location);
        swaggerResource.setSwaggerVersion("3.0");
        return swaggerResource;
    }

    /**
     * 根据服务名称检查nacos的健康状态，以判断要不要添加到swagger文档
     *
     * @param serviceName
     * @return boolean
     * @author George
     * @date 2023/8/8 16:00
     */

    private boolean checkServiceHealth(String serviceName) {
        List<ServiceInstance> instances = discoveryClient.getInstances(serviceName);
        if (!instances.isEmpty()) {
            SimpleClientHttpRequestFactory requestFactory = new SimpleClientHttpRequestFactory();
            RestTemplate restTemplate = new RestTemplate(requestFactory);
            for (ServiceInstance instance : instances) {
                String healthEndpoint = instance.getUri() + "/actuator/health"; // Assuming health endpoint URL
                ResponseEntity<String> response = restTemplate.getForEntity(healthEndpoint, String.class);
                String healthStatus = response.getBody(); // Assuming the response contains health status
                JSONObject jsonObject = JSON.parseObject(healthStatus);
                if (healthStatus != null && ("UP").equalsIgnoreCase(jsonObject.getString("status"))) {
                    return true; // Enable Swagger if at least one instance is UP
                }
            }
        }
        return false;
    }

}


